package com.qianli.cashmama.trade.domain.model;


import com.qianli.cashmama.trade.common.enums.TradeAuditSubStatusEnum;
import com.qianli.cashmama.trade.common.enums.TradeSignStatusEnum;
import com.qianli.cashmama.trade.common.enums.TradeStatusEnum;
import com.qianli.cashmama.trade.common.error.TradeErrorCodeEnum;
import com.qianli.cashmama.trade.common.exceptions.TradeException;
import com.qianli.cashmama.trade.domain.StateMachine;
import com.qianli.cashmama.trade.domain.event.TradeFlow;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
 * Created with IntelliJ IDEA.
 * User: sm
 * Date: 2017/7/20
 * Time: 下午3:00
 */
public class TradeBase extends BaseModel {

    private static final Logger LOGGER = LoggerFactory.getLogger(TradeBase.class);

    private static final long serialVersionUID = 759163691504449250L;

    private List<TradeFlow> tradeFlows = new ArrayList<>();

    private Long tradeId;

    /**
     * 交易编码
     */
    private String tradeNo;
    /**
     * 商户code
     */
    private String merchantCode;
    /**
     * 客户code
     */
    private String customerCode;
    /**
     * 用户code
     */
    private String userCode;
    /**
     * 渠道code
     */
    private String channelCode;
    /**
     * 产品code
     */
    private String productCode;

    /**
     * 产品类目
     */
    private String productCategory;

    /**
     * 客户端类型
     */
    private com.qianli.cashmama.trade.common.enums.TradeClientTypeEnum clientType;
    /**
     * 订单类型
     */
    private com.qianli.cashmama.trade.common.enums.TradeTypeEnum tradeOrderType;
    /**
     * 订单状态
     */
    private com.qianli.cashmama.trade.common.enums.TradeStatusEnum tradeOrderStatus;
    /**
     * 签名状态
     */
    private TradeSignStatusEnum tradeSignStatus;
    /**
     * 信审状态
     */
    private com.qianli.cashmama.trade.common.enums.TradeAuditStatusEnum tradeAuditStatus;
    /**
     * 信审子状态 0-审核中 1-通过 2-拒绝 3-等待highmark
     */
    private TradeAuditSubStatusEnum tradeAuditSubStatus;
    /**
     * 支付状态
     */
    private com.qianli.cashmama.trade.common.enums.TradePayStatusEnum tradePayStatus;


    /**
     * 借款总金额
     */
    private BigDecimal borrowTotalCapital;
    /**
     * 到账总金额
     */
    private BigDecimal receivedTotalCapital;
    /**
     * 应还总金额
     */
    private BigDecimal repaymentTotalCapital;
    /**
     * 已还总金额
     */
    private BigDecimal paidTotalCapital;
    /**
     * 优惠总金额
     */
    private BigDecimal discountTotalCapital;
    /**
     * 总服务费
     */
    private BigDecimal totalServiceFee;
    /**
     * 借款利率
     */
    private BigDecimal borrowRatio;
    /**
     * 服务费率（个税贷）
     */
    private BigDecimal serviceFeeRate;
    /**
     * 总期数
     */
    private Integer totalPeriod;
    /**
     * 已还期数
     */
    private Integer paidPeriod;
    /**
     * 借款周期
     */
    private Integer borrowDuration;
    /**
     * 总逾期服务费
     */
    private BigDecimal totalOverdueServiceFee;
    /**
     * 总逾期费
     */
    private BigDecimal totalOverdueFee;

    /**
     * 单次账单逾期应该缴纳的费用
     */
    private BigDecimal overdueServiceFee;

    /**
     * 逾期利率
     */
    private BigDecimal overdueRatio;
    /**
     * 信审反馈时间
     */
    private Date auditDate;
    /**
     * 到账时间
     */
    private Date receivedDate;
    /**
     * 还清时间
     */
    private Date payOffDate;
    /**
     * 交易编码
     */
    private String payNo;

    /**
     * 交易风控信息
     */
    private List<TradeRisk> tradeRisks;

    /**
     * 交易银行卡信息
     */
    private TradeBank tradeBank;

    /**
     * 交易优惠信息
     */
    private List<TradeDiscount> tradeDiscountList;

    /**
     * 是否是新客
     */
    private boolean isNewUser;

    /**
     * 周期长度
     */
    private int periodLength;

    /**
     * 创建时间
     */
    private Date createdDate;

    /**
     * 操作者
     */
    private String operator = "system";

    /**
     * 资金方
     */
    private Integer capitalCode;

    private String remark;
    /**
     * 借款用途
     */
    private com.qianli.cashmama.trade.common.enums.UsageOfLoanEnum usageOfLoan;

    /**
     * 息费支付流水号
     */
    private String servicefeePayflowNo;

    /**
     * 当前交易合同地址
     */
    private String contractUrl;
    private String documentId;
    /**
     * 合同的签署时间
     */
    private Date signDate;

    /**
     * 额外信息
     */
    private String extraData;

    public String getMerchantCode() {
        return merchantCode;
    }

    public TradeBase setMerchantCode(String merchantCode) {
        this.merchantCode = merchantCode;
        return this;
    }

    public String getExtraData() {
        return extraData;
    }

    public TradeBase setExtraData(String extraData) {
        this.extraData = extraData;
        return this;
    }

    public String getDocumentId() {
        return documentId;
    }

    public void setDocumentId(String documentId) {
        this.documentId = documentId;
    }

    public Date getSignDate() {
        return signDate;
    }

    public TradeBase setSignDate(Date signDate) {
        this.signDate = signDate;
        return this;
    }

    public String getContractUrl() {
        return contractUrl;
    }

    public TradeBase setContractUrl(String contractUrl) {
        this.contractUrl = contractUrl;
        return this;
    }

    public String getServicefeePayflowNo() {
        return servicefeePayflowNo;
    }

    public void setServicefeePayflowNo(String servicefeePayflowNo) {
        this.servicefeePayflowNo = servicefeePayflowNo;
    }

    public com.qianli.cashmama.trade.common.enums.UsageOfLoanEnum getUsageOfLoan() {
        return usageOfLoan;
    }

    public TradeBase setUsageOfLoan(com.qianli.cashmama.trade.common.enums.UsageOfLoanEnum usageOfLoan) {
        this.usageOfLoan = usageOfLoan;
        return this;
    }

    public TradeBase setTradeFlows(List<TradeFlow> tradeFlows) {
        this.tradeFlows = tradeFlows;
        return this;
    }

    public Integer getCapitalCode() {
        return capitalCode;
    }

    public TradeBase setCapitalCode(Integer capitalCode) {
        this.capitalCode = capitalCode;
        return this;
    }

    public String getOperator() {
        return operator;
    }

    public TradeBase setOperator(String operator) {
        this.operator = operator;
        return this;
    }

    public Long getTradeId() {
        return tradeId;
    }

    public TradeBase setTradeId(Long tradeId) {
        this.tradeId = tradeId;
        return this;
    }

    public Date getCreatedDate() {
        return createdDate;
    }

    public TradeBase setCreatedDate(Date createdDate) {
        this.createdDate = createdDate;
        return this;
    }

    public int getPeriodLength() {
        return periodLength;
    }

    public TradeBase setPeriodLength(int periodLength) {
        this.periodLength = periodLength;
        return this;
    }

    public boolean isNewUser() {
        return isNewUser;
    }

    public TradeBase setNewUser(boolean newUser) {
        isNewUser = newUser;
        return this;
    }

    public String getProductCategory() {
        return productCategory;
    }

    public TradeBase setProductCategory(String productCategory) {
        this.productCategory = productCategory;
        return this;
    }

    public BigDecimal getOverdueServiceFee() {
        return overdueServiceFee;
    }

    public TradeBase setOverdueServiceFee(BigDecimal overdueServiceFee) {
        this.overdueServiceFee = overdueServiceFee;
        return this;
    }

    public com.qianli.cashmama.trade.common.enums.TradeClientTypeEnum getClientType() {
        return clientType;
    }

    public TradeBase setClientType(com.qianli.cashmama.trade.common.enums.TradeClientTypeEnum clientType) {
        this.clientType = clientType;
        return this;
    }

    public List<TradeDiscount> getTradeDiscountList() {
        return tradeDiscountList;
    }

    public TradeBase setTradeDiscountList(List<TradeDiscount> tradeDiscountList) {
        this.tradeDiscountList = tradeDiscountList;
        return this;
    }

    public TradeBank getTradeBank() {
        return tradeBank;
    }

    public TradeBase setTradeBank(TradeBank tradeBank) {
        this.tradeBank = tradeBank;
        return this;
    }

    public List<TradeRisk> getTradeRisks() {
        return tradeRisks;
    }

    public TradeBase setTradeRisks(List<TradeRisk> tradeRisks) {
        this.tradeRisks = tradeRisks;
        return this;
    }


    public String getTradeNo() {
        return tradeNo;
    }

    public TradeBase setTradeNo(String tradeNo) {
        this.tradeNo = tradeNo;
        return this;
    }

    public String getCustomerCode() {
        return customerCode;
    }

    public TradeBase setCustomerCode(String customerCode) {
        this.customerCode = customerCode;
        return this;
    }

    public String getUserCode() {
        return userCode;
    }

    public TradeBase setUserCode(String userCode) {
        this.userCode = userCode;
        return this;
    }

    public String getChannelCode() {
        return channelCode;
    }

    public TradeBase setChannelCode(String channelCode) {
        this.channelCode = channelCode;
        return this;
    }

    public String getProductCode() {
        return productCode;
    }

    public TradeBase setProductCode(String productCode) {
        this.productCode = productCode;
        return this;
    }

    public BigDecimal getBorrowTotalCapital() {
        return borrowTotalCapital;
    }

    public TradeBase setBorrowTotalCapital(BigDecimal borrowTotalCapital) {
        this.borrowTotalCapital = borrowTotalCapital;
        return this;
    }

    public BigDecimal getReceivedTotalCapital() {
        return receivedTotalCapital;
    }

    public TradeBase setReceivedTotalCapital(BigDecimal receivedTotalCapital) {
        this.receivedTotalCapital = receivedTotalCapital;
        return this;
    }

    public BigDecimal getRepaymentTotalCapital() {
        return repaymentTotalCapital;
    }

    public TradeBase setRepaymentTotalCapital(BigDecimal repaymentTotalCapital) {
        this.repaymentTotalCapital = repaymentTotalCapital;
        return this;
    }

    public BigDecimal getPaidTotalCapital() {
        return paidTotalCapital;
    }

    public TradeBase setPaidTotalCapital(BigDecimal paidTotalCapital) {
        this.paidTotalCapital = paidTotalCapital;
        return this;
    }

    public BigDecimal getDiscountTotalCapital() {
        return discountTotalCapital;
    }

    public TradeBase setDiscountTotalCapital(BigDecimal discountTotalCapital) {
        this.discountTotalCapital = discountTotalCapital;
        return this;
    }

    public BigDecimal getTotalServiceFee() {
        return totalServiceFee;
    }

    public TradeBase setTotalServiceFee(BigDecimal totalServiceFee) {
        this.totalServiceFee = totalServiceFee;
        return this;
    }

    public BigDecimal getBorrowRatio() {
        return borrowRatio;
    }

    public TradeBase setBorrowRatio(BigDecimal borrowRatio) {
        this.borrowRatio = borrowRatio;
        return this;
    }

    public BigDecimal getServiceFeeRate() {
        return serviceFeeRate;
    }

    public TradeBase setServiceFeeRate(BigDecimal serviceFeeRate) {
        this.serviceFeeRate = serviceFeeRate;
        return this;
    }

    public Integer getTotalPeriod() {
        return totalPeriod;
    }

    public TradeBase setTotalPeriod(Integer totalPeriod) {
        this.totalPeriod = totalPeriod;
        return this;
    }

    public Integer getPaidPeriod() {
        return paidPeriod;
    }

    public TradeBase setPaidPeriod(Integer paidPeriod) {
        this.paidPeriod = paidPeriod;
        return this;
    }

    public Integer getBorrowDuration() {
        return borrowDuration;
    }

    public TradeBase setBorrowDuration(Integer borrowDuration) {
        this.borrowDuration = borrowDuration;
        return this;
    }

    public BigDecimal getTotalOverdueServiceFee() {
        return totalOverdueServiceFee;
    }

    public TradeBase setTotalOverdueServiceFee(BigDecimal totalOverdueServiceFee) {
        this.totalOverdueServiceFee = totalOverdueServiceFee;
        return this;
    }

    public BigDecimal getTotalOverdueFee() {
        return totalOverdueFee;
    }

    public TradeBase setTotalOverdueFee(BigDecimal totalOverdueFee) {
        this.totalOverdueFee = totalOverdueFee;
        return this;
    }

    public BigDecimal getOverdueRatio() {
        return overdueRatio;
    }

    public TradeBase setOverdueRatio(BigDecimal overdueRatio) {
        this.overdueRatio = overdueRatio;
        return this;
    }

    public Date getAuditDate() {
        return auditDate;
    }

    public TradeBase setAuditDate(Date auditDate) {
        this.auditDate = auditDate;
        return this;
    }

    public Date getReceivedDate() {
        return receivedDate;
    }

    public TradeBase setReceivedDate(Date receivedDate) {
        this.receivedDate = receivedDate;
        return this;
    }

    public Date getPayOffDate() {
        return payOffDate;
    }

    public TradeBase setPayOffDate(Date payOffDate) {
        this.payOffDate = payOffDate;
        return this;
    }

    public String getPayNo() {
        return payNo;
    }

    public TradeBase setPayNo(String payNo) {
        this.payNo = payNo;
        return this;
    }

    public com.qianli.cashmama.trade.common.enums.TradeTypeEnum getTradeOrderType() {
        return tradeOrderType;
    }

    public TradeBase setTradeOrderType(com.qianli.cashmama.trade.common.enums.TradeTypeEnum tradeOrderType) {
        this.tradeOrderType = tradeOrderType;
        return this;
    }

    public com.qianli.cashmama.trade.common.enums.TradeStatusEnum getTradeOrderStatus() {
        return tradeOrderStatus;
    }

    public TradeBase setTradeOrderStatus(com.qianli.cashmama.trade.common.enums.TradeStatusEnum tradeOrderStatus) {
        this.tradeOrderStatus = tradeOrderStatus;
        return this;
    }

    public com.qianli.cashmama.trade.common.enums.TradeAuditStatusEnum getTradeAuditStatus() {
        return tradeAuditStatus;
    }

    public TradeBase setTradeAuditStatus(com.qianli.cashmama.trade.common.enums.TradeAuditStatusEnum tradeAuditStatus) {
        this.tradeAuditStatus = tradeAuditStatus;
        return this;
    }

    public TradeAuditSubStatusEnum getTradeAuditSubStatus() {
        return tradeAuditSubStatus;
    }

    public TradeBase setTradeAuditSubStatus(TradeAuditSubStatusEnum tradeAuditSubStatus) {
        this.tradeAuditSubStatus = tradeAuditSubStatus;
        return this;
    }

    public com.qianli.cashmama.trade.common.enums.TradePayStatusEnum getTradePayStatus() {
        return tradePayStatus;
    }

    public TradeBase setTradePayStatus(com.qianli.cashmama.trade.common.enums.TradePayStatusEnum tradePayStatus) {
        this.tradePayStatus = tradePayStatus;
        return this;
    }

    public String getRemark() {
        return remark;
    }

    public TradeBase setRemark(String remark) {
        this.remark = remark;
        return this;
    }

    public TradeSignStatusEnum getTradeSignStatus() {
        return tradeSignStatus;
    }

    public TradeBase setTradeSignStatus(TradeSignStatusEnum tradeSignStatus) {
        this.tradeSignStatus = tradeSignStatus;
        return this;
    }

    public List<TradeFlow> getTradeFlows() {
        return tradeFlows;
    }

    @Override
    protected void doTransferStatus(String action, int targetStatus, String operator, Date operationDt, Date bizDt, String memo) {
        StateMachine stateMachine = getStatusMachine();
        boolean statusChangeAllowed = stateMachine.checkTransition(this.tradeOrderStatus.getStatus(), action, targetStatus);
        if (!statusChangeAllowed) {
            LOGGER.error("doTransferStatus params: orderStatus={}, action={}, targetStatus={}, bizDt={}, memo={}", this.getTradeOrderStatus().getStatus(), action, targetStatus, bizDt, memo);
            throw new TradeException(TradeErrorCodeEnum.trade_status_transfer_error);
        }
        TradeFlow tradeFlow = new TradeFlow(tradeNo, action, tradeOrderStatus, com.qianli.cashmama.trade.common.enums.TradeStatusEnum.convertByStatus(targetStatus), operationDt)
                .setNote(com.qianli.cashmama.trade.common.enums.TradeStatusEnum.convertByStatus(targetStatus).getDesc());
        tradeFlows.add(tradeFlow);

        this.tradeOrderStatus = TradeStatusEnum.convertByStatus(targetStatus);
    }

    @Override
    protected StateMachine getStatusMachine() {
        return TradeBaseState.getStateTransitionDef();
    }

    public void clearEvent() {
        this.tradeFlows = new ArrayList<>();
    }


}
